'''
Created on 10/12/2014

@author: David
'''
from Sodev.kernel import Kernel
from Sodev.program import Program
from Sodev.Instr import Instr
from Sodev.scheduler import Scheduler
from Sodev.cpu import Cpu
from Sodev.memoryAdmin import Memoryadmin
from Sodev.clock import Clock
from Sodev.irqKill import IRQKill
from Sodev.IOInstr import IOInstr
from Sodev.IO import IO
from Sodev.CPUInstr import CPUInstr
from Sodev.schedulerQueueP import SchedulerQueueP
from Sodev.handlerPCB import HandlerPCB
from Sodev.SchedulerRoundRobin import SchedulerRoundRobin
from Sodev.CompactacionParaArriba import CompactacionParaArriba
from Sodev.CompactacionParaAbajo import CompactacionParaAbajo
from Sodev.Block import Block
from Sodev.asignacionContinua import AsignacionContinua
from Sodev.firstFit import FirstFit
from Sodev.fileSystem import FileSystem
from Sodev.hardDrive import Harddrive
from Sodev.file import File
from Sodev.folder import Folder
from Sodev.worstFit import WorstFit
from Sodev.bestFit import BestFit

class Main:
    
    def __init__(self):
        #Estrategias de MMU
        self.firstFit = FirstFit()
        self.worstFit = WorstFit()
        self.bestFit = BestFit()
        
        #Estrategias de compactacion       
        self.compactacionParaArriba = CompactacionParaArriba()
        self.compactacionParaAbajo = CompactacionParaAbajo()
        
        self.MMU= Memoryadmin()
        
        #Seteo de clock y CPU
        self.clock = Clock(None)
        self.handlerPCB = HandlerPCB(None)
        cpu = Cpu(self.MMU,self.clock, self.handlerPCB)      
        self.clock.setCpu(cpu)
        
        #Schedulers
        self.schedulerFifo = Scheduler(cpu)
        self.schedulerPriorityQueue = SchedulerQueueP(cpu) 
        self.schedulerRoundRobin= SchedulerRoundRobin(cpu)
        
        #Se inicia luego con los presets o el custom.
        self.kernel = None
              
    #Metodo para iniciar el Kernel manualmente.
    def setKernelwith(self, stratCompacter, stratSelectblock, tipeScheduler):
       
        #self.MMU.setAsignacionContinua(stratCompacter,stratSelectblock)
        self.kernel = Kernel(tipeScheduler)
        self.kernel.setMMU(self.MMU)
        self.MMU.setPaginacion(self.kernel.harddrive)
        self.handlerPCB.setKernel(self.kernel)
        self.handlerPCB.iniciarHandlers()
     
    #Kernels predefinidos       
    def setKernelModeI(self):
        self.setKernelwith(self.compactacionParaAbajo, self.firstFit, self.schedulerFifo)
    
    def setKernelModeII(self):   
        self.setKernelwith(self.compactacionParaArriba, self.firstFit, self.schedulerFifo)
    
    def setKernelModeIII(self):
        self.setKernelwith(self.compactacionParaAbajo,  self.bestFit, self.schedulerPriorityQueue)
        
    def setKernelModeIV(self):
        self.setKernelwith(self.compactacionParaArriba, self.worstFit, self.schedulerPriorityQueue)
        
    def setKernelModeV(self):
        self.setKernelwith(self.compactacionParaArriba, self.firstFit, self.schedulerRoundRobin)
    
    def setKernelModeVI(self):
        self.setKernelwith(self.compactacionParaAbajo, self.bestFit, self.schedulerRoundRobin)
    
    
    #genera una lista de programas.
    def generatePrograms(self, cantPrograms, cantInstruccion):
        programTmp = None
        cantInstruccionTmp = cantInstruccion
        cantProgramsTmp = cantPrograms
        programs = []
        while(cantProgramsTmp > 0):
            programTmp = Program("test" + str(cantProgramsTmp))
            
            while(cantInstruccionTmp > 0):
                programTmp.addInstr(CPUInstr())
                cantInstruccionTmp = cantInstruccionTmp -1
                
            cantProgramsTmp = cantProgramsTmp -1
            cantInstruccionTmp = cantInstruccion
            programs.append(programTmp)
        
        return programs
    
    #espera una lista de programas a instalar en el path indicado.
    #asume que el Kernel esta seteado correctamente.
    def installPrograms(self, path, programs):
        for prog in programs:
            self.kernel.writeProgramOnHD(path, prog)
    
    #Metodo para las pruebas.
    def run(self):
        self.setKernelModeV()
        programs = self.generatePrograms(2, 2)
        self.installPrograms("root/", programs)
        self.kernel.runII("root/test1")
        self.kernel.runII("root/test2")
        self.kernel.createFolder("musica", "root/")
        self.installPrograms("root/musica", programs)
        self.kernel.runII("root/musica/test1")
        self.kernel.runII("root/musica/test2")
        self.kernel.runMultiplePrograms(programs)
            
            
if __name__ == "__main__":
    Main().run()
        
        
            
        
        
             
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        